package base

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/vueadmin/app/admin/internal/svc"
	"github.com/vueadmin/pkg/oss"
	"github.com/vueadmin/utils"
	"github.com/vueadmin/utils/common/result"
	"github.com/vueadmin/utils/conv"
	"github.com/vueadmin/utils/response"
	"io/ioutil"
	"path"
	"time"
)

// 上传文件
func Upload(c *gin.Context, svcCtx *svc.ServiceContext) {
	file, err := c.FormFile("file")
	if err != nil {
		response.Fail(c, err.Error())
		return
	}
	rename := c.Request.PostFormValue("rename")
	if rename == "" {
		rename = "1"
	}
	if file.Size > conv.Int64(c.Value("filesize"))*1024*1024 {
		response.Fail(c, "文件大小验证失败")
		return
	}
	fileExt := path.Ext(file.Filename)
	if !utils.FileValid(fileExt, conv.String(c.Value("filetype"))) {
		response.Fail(c, "文件后缀验证失败")
		return
	}
	fileHandle, _ := file.Open()
	defer fileHandle.Close()
	body, err2 := ioutil.ReadAll(fileHandle)
	if err != nil {
		response.Fail(c, err2.Error())
		return
	}
	hash := utils.Md5(string(body))

	//判断是否直接读取数据表中相同的图片记录
	config := svcCtx.Config.Upload
	if config.CheckFileStatus {
		var filePath string
		if filepathErr := svcCtx.Db.Table("cd_file").Where("hash", hash).Limit(1).Pluck("filepath", &filePath).Error; filepathErr != nil {
			response.Err(c, filepathErr)
			return
		}
		if filePath != "" {
			response.Success(c, "上传成功", result.M{
				"filestatus": true,
				"data":       filePath,
			})
			return
		}
	}
	//判断文件是否重命名
	var fileName string
	savepath := fmt.Sprintf("/%s/%s", config.UploadPath, time.Now().Format("200601"))
	if rename == "1" {
		fileName = fmt.Sprintf("%s/%s%s", savepath, hash, fileExt)
	} else {
		fileName = fmt.Sprintf("%s/%s", savepath, file.Filename)
	}
	//判断是否为客户端上传
	if config.UploadType == "client" && conv.IsEmpty(c.Request.PostFormValue("edit")) {
		var data map[string]interface{}
		switch config.Disks {
		case "qiniu":
			data = oss.NewQiniuOss(conv.String(config.QiniuOss)).GetCliendConfig(fileName)
		case "tencent":
			data = oss.NewTencentOss(conv.String(config.TencentCos)).GetCliendConfig(fileName)
		case "ali":
			data = oss.NewAliyunOss(conv.String(config.AliyunOss)).GetCliendConfig(fileName)
		}
		response.Success(c, "success", data)
		return
	}
	switch config.Disks {
	case "local":
		if createDirErr := utils.CreateDir(config.AccessPath + savepath); createDirErr != nil {
			response.Fail(c, createDirErr.Error())
			return
		}
		if uploadErr := c.SaveUploadedFile(file, fmt.Sprintf("%s/%s", config.AccessPath, fileName)); err != nil {
			response.Fail(c, uploadErr.Error())
			return
		}
		fileName = fmt.Sprintf("%s%s", conv.String(c.Value("domain")), fileName)
	case "qiniu":
		fileName = oss.NewQiniuOss(conv.String(config.QiniuOss)).Upload(file, fileName)
	case "ali":
		fileName = oss.NewAliyunOss(conv.String(config.AliyunOss)).Upload(file, fileName)
	case "tencent":
		fileName = oss.NewTencentOss(conv.String(config.TencentCos)).Upload(file, fileName)
	default:
		response.Fail(c, "请设置上传类型!")
		return
	}
	go func() {
		CreateSaveFilepath(svcCtx, fileName, config.Disks, hash)
	}()
	response.Success(c, "success", fileName)
}

// 保存上传图片路径
func CreateSaveFilepath(svcCtx *svc.ServiceContext, filename string, disk string, hash string) {
	data := make(map[string]interface{})
	data["filepath"] = filename
	data["hash"] = hash
	data["create_time"] = conv.NowUnix()
	data["disk"] = disk

	if err := svcCtx.Db.Table("cd_file").Create(&data).Error; err != nil {
		svcCtx.Log.Error("保存图片路径失败:", err)
	}
}
